﻿namespace RockPaperScissors.Web.Utility.Tests
{
    using GravityWorks.RockPaperScissors.Toolkit;
    using NUnit.Framework;
    using RockPaperScissors.Core;
    using RockPaperScissors.Web.Utility.Tests.Mocks;
    
    [TestFixture]
    public class CalculateWinner
    {
        [Test]
        public void Should_Return_TeamOne_Winner_When_Rock_Vs_IntCastToMove()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Rock;
            MoveType secondTeamMove = (MoveType)4691;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Winner_When_Rock_Vs_Scissors()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Rock;
            MoveType secondTeamMove = MoveType.Scissors;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Winner_When_Paper_Vs_Rock()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Paper;
            MoveType secondTeamMove = MoveType.Rock;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Winner_When_Scissors_Vs_Paper()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Scissors;
            MoveType secondTeamMove = MoveType.Paper;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Winner_When_Dynamite_Vs_Paper()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, true, 3);
            MoveType firstTeamMove = MoveType.Dynamite;
            MoveType secondTeamMove = MoveType.Paper;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Winner_When_Dynamite_Vs_Rock()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, true, 3); ;
            MoveType firstTeamMove = MoveType.Dynamite;
            MoveType secondTeamMove = MoveType.Rock;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Winner_When_Dynamite_Vs_Scissors()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, true, 3);
            MoveType firstTeamMove = MoveType.Dynamite;
            MoveType secondTeamMove = MoveType.Scissors;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Lose_When_Scissors_Vs_Rock()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Scissors;
            MoveType secondTeamMove = MoveType.Rock;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsFalse(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Lose_When_Rock_Vs_Paper()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Rock;
            MoveType secondTeamMove = MoveType.Paper;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsFalse(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Winner_When_Paper_Vs_Scissors()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Paper;
            MoveType secondTeamMove = MoveType.Scissors;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsFalse(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_Tie_When_Paper()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Paper;
            MoveType secondTeamMove = MoveType.Paper;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.IsTie == true);
            Assert.IsTrue(result.WinnerTeamName == "Tie");
        }

        [Test]
        public void Should_Return_Tie_When_Rock()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Rock;
            MoveType secondTeamMove = MoveType.Rock;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.IsTie == true);
            Assert.IsTrue(result.WinnerTeamName == "Tie");
        }

        [Test]
        public void Should_Return_Tie_When_Scissors()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Scissors;
            MoveType secondTeamMove = MoveType.Scissors;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.IsTie == true);
            Assert.IsTrue(result.WinnerTeamName == "Tie");
        }

        [Test]
        public void Should_Return_Tie_When_Dynamite()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, true, 3);
            MoveType firstTeamMove = MoveType.Dynamite;
            MoveType secondTeamMove = MoveType.Dynamite;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.IsTie == true);
            Assert.IsTrue(result.WinnerTeamName == "Tie");
        }

        [Test]
        public void Should_Return_TeamTwo_Win_When_Dynamite_Vs_Rock()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, true, 3);
            MoveType firstTeamMove = MoveType.Rock;
            MoveType secondTeamMove = MoveType.Dynamite;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team2");
        }

        [Test]
        public void Should_Return_TeamOne_Loss_When_They_Have_Used_All_Their_Dynamite()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, true, 3);
            MoveType firstTeamMove = MoveType.Dynamite;
            MoveType secondTeamMove = MoveType.Rock;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            GameLog gameLog = new GameLog().CreateGameLogWithNoDynamiteLeftForTeam("team1", 3);
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, gameLog);

            Assert.IsTrue(result.WinnerTeamName == "team2");
        }

        [Test]
        public void Should_Return_TeamTwo_Loss_When_They_Have_Used_All_Their_Dynamite()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, true, 3);
            MoveType firstTeamMove = MoveType.Rock;
            MoveType secondTeamMove = MoveType.Dynamite;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            GameLog gameLog = new GameLog().CreateGameLogWithNoDynamiteLeftForTeam("team1", 3);
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, gameLog);

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_ReturnTeamTwo_Loss_When_They_Throw_An_Exception()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, true, 3);
            IPlayer team = new ExceptionPlayer();
            MoveType move = CompeteHelper.GetShot(team, new GameLog(), ruleSet, 1);

            Assert.IsTrue(move == MoveType.None);
        }

        [Test]
        public void Should_Return_Tie_When_Both_Teams_Throw_An_Exception()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, true, 3);
            var gameLog = new GameLog();
            IPlayer team = new ExceptionPlayer();
            IPlayer team2 = new ExceptionPlayer();
            MoveType move = CompeteHelper.GetShot(team, new GameLog(), ruleSet, 1);
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, MoveType.None, secondTeamName, MoveType.None, ruleSet, gameLog);

            Assert.IsTrue(result.WinnerTeamName == "Tie");
        }

        [Test]
        public void Should_Return_TeamOne_Loss_When_None_Vs_Rock()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.None;
            MoveType secondTeamMove = MoveType.Scissors;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team2");
        }

        [Test]
        public void Should_Return_TeamOne_Win_When_Rock_Vs_None()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Rock;
            MoveType secondTeamMove = MoveType.None;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Win_When_Scissors_Vs_None()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Scissors;
            MoveType secondTeamMove = MoveType.None;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Win_When_Paper_Vs_None()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, false, 0);
            MoveType firstTeamMove = MoveType.Paper;
            MoveType secondTeamMove = MoveType.None;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }

        [Test]
        public void Should_Return_TeamOne_Win_When_Dynamite_Vs_None()
        {
            RuleSet ruleSet = new RuleSet().CreateRuleSet(true, true, true, true, 1);
            MoveType firstTeamMove = MoveType.Dynamite;
            MoveType secondTeamMove = MoveType.None;
            IPlayer firstTeam = new MockPlayer();
            IPlayer secondTeam = new MockPlayer();
            string firstTeamName = "team1";
            string secondTeamName = "team2";
            MatchResult result = CompeteHelper.CalculateWinner(firstTeamName, firstTeamMove, secondTeamName, secondTeamMove, ruleSet, new GameLog());

            Assert.IsTrue(result.WinnerTeamName == "team1");
        }
    }
}
